package com.chen.androidstudy.utils;

import android.annotation.SuppressLint;
import android.content.Context;
import android.location.Address;
import android.location.Criteria;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.widget.Toast;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.List;
import java.util.Locale;

@SuppressLint("MissingPermission")
public class GPSManage {
    private static final String TAG = "GPSUtils";
    private LocationManager mLocationManager;
    private Location mLocation = null;
    private Context mContext;
    private static GPSManage mInstance;
    private String bestProvider;

    private LocationBackListener mLocationBackListener;

    private GPSManage() {

    }

    public static GPSManage getInstance() {
        if (mInstance == null) {
            mInstance = new GPSManage();
        }
        return mInstance;
    }


    public void initGps(Context context) {
        this.mContext = context;
        if (mLocationManager == null) {
            mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
            if (mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
                Logger.e(TAG, "initGps open succs: ");
            } else {
                Logger.e(TAG, "initGps: fil");
            }
            // 获取位置信息
            // 若是不设置查询要求，getLastKnownLocation方法传人的参数为LocationManager.GPS_PROVIDER
            // 绑定监听，有4个参数
            // 参数1，设备：有GPS_PROVIDER和NETWORK_PROVIDER两种
            // 参数2，位置信息更新周期，单位毫秒
            // 参数3，位置变化最小距离：当位置距离变化超过此值时，将更新位置信息
            // 参数4，监听
            // 备注：参数2和3，若是参数3不为0，则以参数3为准；参数3为0，则经过时间来定时更新；二者为0，则随时刷新

            // 1秒更新一次，或最小位移变化超过1米更新一次；
            // 注意：此处更新准确度很是低，推荐在service里面启动一个Thread，在run中sleep(10000);而后执行handler.sendMessage(),更新位置
//        mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, locationListener);

            gpsRequestLocationUpdates();
        }

    }

    /**
     * 返回查询条件
     *
     * @return
     */
    private Criteria getCriteria() {
        Criteria criteria = new Criteria();
        // 设置定位精确度 Criteria.ACCURACY_COARSE比较粗略，Criteria.ACCURACY_FINE则比较精细
        criteria.setAccuracy(Criteria.ACCURACY_FINE);
        // 设置是否要求速度
        criteria.setSpeedRequired(true);
        // 设置是否容许运营商收费
        criteria.setCostAllowed(false);
        // 设置是否须要方位信息
        criteria.setBearingRequired(true);
        // 设置是否须要海拔信息
        criteria.setAltitudeRequired(true);
        // 设置对电源的需求
        criteria.setPowerRequirement(Criteria.POWER_LOW);
        return criteria;
    }

    /**
     * @return Location--->getLongitude()获取经度/getLatitude()获取纬度
     */
    public Location getLocation() {
        if (mLocation == null && mLocationManager != null) {
            Logger.d(TAG, "GPSUtils，setLocationData: 获取当前位置信息为空");
//            mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, locationListener);
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    gpsRequestLocationUpdates();
                }
            });
            return mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
        }
        return mLocation;
    }

    /**
     * 判断GPS 信号环境，动态获取定位信息GPSUtilscountry
     */
    private void gpsRequestLocationUpdates() {
        if (mLocationManager != null && locationListener != null) {
            mLocationManager.removeUpdates(locationListener);
            List<String> proverList = mLocationManager.getProviders(true);
            String provider = LocationManager.GPS_PROVIDER;
            if (proverList.contains(LocationManager.NETWORK_PROVIDER)) {
                provider = LocationManager.NETWORK_PROVIDER;
            } else if (proverList.contains(LocationManager.GPS_PROVIDER)) {
                provider = LocationManager.GPS_PROVIDER;
            } else if (proverList.contains(LocationManager.PASSIVE_PROVIDER)) {
                provider = LocationManager.PASSIVE_PROVIDER;
            } else {
                return;
            }
            mLocationManager.requestLocationUpdates(provider, 1000, 1, locationListener);
        }
    }

    /**
     * 根据地址获取国家编码
     *
     * @param result
     * @return
     */
    private String fromAddressGetCountryCode(List<Address> result) {
        String countryCode = "";
        if (result != null && result.size() > 0) {
            for (Address address : result) {
                countryCode = address.getCountryCode();
                if (!TextUtils.isEmpty(countryCode) && !"null".equals(countryCode)) {
                    break;
                }
            }
        }

        return countryCode;
    }

    public String getLocalCity() {
        if (mLocation == null) {
            Logger.e("GPSUtils", "getLocalCity: 获取城市信息为空");
            return "";
        }
        List<Address> result = getAddress(mLocation);

        String city = "";
        if (result != null && result.size() > 0) {
            result.get(0).getCountryCode();
            city = result.get(0).getLocality();//获取城市
        }
        return city;
    }

    public String getAddressStr() {
        if (mLocation == null) {
            Logger.e("GPSUtils", "getAddressStr: 获取详细地址信息为空");
            return "";
        }
        List<Address> result = getAddress(mLocation);

        String address = "";
        if (result != null && result.size() > 0) {
            address = result.get(0).getAddressLine(0);//获取详细地址
        }
        return address;
    }

    // 位置监听
    private LocationListener locationListener = new LocationListener() {

        //位置信息变化时触发
        public void onLocationChanged(Location location) {
            mLocation = location;
            getLocationMsg();
            if (mLocationBackListener != null) {
                mLocationBackListener.onLocationBack();
            }
        }

        //GPS状态变化时触发
        public void onStatusChanged(String provider, int status, Bundle extras) {
            switch (status) {
                // GPS状态为可见时
                case LocationProvider.AVAILABLE:
                    Logger.d(TAG, "当前GPS状态为可见状态");
                    break;
                // GPS状态为服务区外时
                case LocationProvider.OUT_OF_SERVICE:
                    Logger.d(TAG, "当前GPS状态为服务区外状态");
                    break;
                // GPS状态为暂停服务时
                case LocationProvider.TEMPORARILY_UNAVAILABLE:
                    Logger.d(TAG, "当前GPS状态为暂停服务状态");
                    break;
            }
        }

        //GPS开启时触发
        public void onProviderEnabled(String provider) {
            Location location = mLocationManager.getLastKnownLocation(provider);
            mLocation = location;
            Logger.d(TAG, location.getLatitude() + " " + location.getLongitude());
        }

        //GPS禁用时触发
        public void onProviderDisabled(String provider) {
            mLocation = null;
        }
    };

    public boolean isLocationEnabled() {
        if (mLocationManager == null) {
            return false;
        }
        return mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) ||
                mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
    }

    public String getLocationMsg() {
        String msg = "";
        if (mLocation != null) {
            Logger.e(TAG, "描述：" + mLocation.getProvider() + mLocation.getAltitude() + mLocation.describeContents());
            Logger.e(TAG, "时间：" + mLocation.getTime());
            Logger.e(TAG, "经度：" + mLocation.getLongitude());
            Logger.e(TAG, "纬度：" + mLocation.getLatitude());
            Logger.e(TAG, "海拔：" + mLocation.getAltitude());
            msg += "描述：" + mLocation.getProvider() + " " + mLocation.getAltitude() + " " + mLocation.describeContents() + "\n";
            msg += "时间：" + mLocation.getTime() + "\n";
            msg += "经度：" + mLocation.getLongitude() + "\n";
            msg += "纬度：" + mLocation.getLatitude() + "\n";
            msg += "海拔：" + mLocation.getAltitude() + "\n";
        }
        return msg;
    }

    // 获取地址信息
    public List<Address> getAddress(Location location) {
        List<Address> result = null;
        try {
            Logger.d(TAG, " to address: location: " + location.getLatitude() + ", " + location.getLongitude());
            if (location != null) {
//                Geocoder gc = new Geocoder(mContext, Locale.ENGLISH);
                Geocoder gc = new Geocoder(mContext, Locale.getDefault());
                result = gc.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
            }
        } catch (Exception e) {
            Logger.d(TAG, " obtain address exception: " + e);
            e.printStackTrace();
        } finally {
            if (result != null && !result.isEmpty()) {
                for (Address adr : result) {
                    Logger.d(TAG, " obtain address: " + adr);
                    Logger.d(TAG, " obtain address is: " + adr.getCountryCode());
                }
            } else {
                Logger.d(TAG, " obtain address is:  result is null");
            }
            return result;
        }
    }

    /**
     * 根据定位获取地理位置
     *
     * @param mLocation
     * @return
     */
    public Address getLocationAddress(Location mLocation) {
        Address address = null;
        Geocoder geocoder = new Geocoder(mContext);
        try {
            List<Address> list = geocoder.getFromLocation(mLocation.getLatitude(), mLocation.getLongitude(), 1);
            for (int i = 0; i < list.size(); i++) {
                address = list.get(i);

                Logger.e(TAG, "地理位置：" + address);

                // 只能获取到地理文字，没有邮政编码
//                Logger.e(TAG, "地理位置：" + address.getCountryName() + address.getFeatureName());
//                address.getCountryName();// 国家
//                address.getAdminArea();// 省
//                address.getLocality();// 市
//                address.getSubLocality();// 区
//                address.getFeatureName();// 详细地理位置
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        return address;
    }

    /**
     * 注销
     */

    public void unregister() {
        removeLocationBackListener();
        if (mLocationManager != null) {
            mLocationManager.removeUpdates(locationListener);
            mLocationManager = null;
        }
        mContext = null;
    }

    public void addLocationBackListener(LocationBackListener mLocationBackListener) {
        this.mLocationBackListener = mLocationBackListener;
    }

    public void removeLocationBackListener() {
        this.mLocationBackListener = null;
    }

    public interface LocationBackListener {
        public void onLocationBack();
    }


    /**
     * 获取定位的地址
     *
     * @return
     */
    public String getGeolocation() {
        // 获取定位地址
        Location mLocation = getLocation();

        if (mLocation == null) {
            return "";
        }
        double lat = mLocation.getLatitude();
        double lon = mLocation.getLongitude();
        if (lat <= 0 || lon <= 0) {
            return "";
        }

        // 保留5位小数
        String latStr = doubleToDecimal5(lat);
        String lonStr = doubleToDecimal5(lon);

        return "geolocation=\"" + latStr + "-" + lonStr + "\"";
    }

    /**
     * 保留5位小数
     *
     * @return
     */
    public String doubleToDecimal5(double d) {
        BigDecimal b = new BigDecimal(d + "");
        return b.setScale(5, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString();
    }

}
